package org.openzip.openzip.gui.util;


import javax.swing.*;

import org.openzip.openzip.gui.util.checkBox.FileCheckBoxModel;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.*;

/**
 * This is an extension of the <code>JList</code> class. This list has been
 * modified to provide interface for selecting files. It displays elements as
 * file names with file icon and a checkbox. Selecting the element will select
 * the file. For displaying files, it uses the <code>FileCheckBox</code> class.
 * 
 * @author Jakub Závěrka.
 */
class FileCheckList extends JList
{
	private DefaultListModel model;
	
	/**
	 * Constructor. It initializes the component and the underlying model, as
	 * well as member fields.
	 */
	FileCheckList(){
		model = new DefaultListModel();
		//mapping = new HashMap<File, JCheckBox>();
		setModel(model);
		setCellRenderer(new CheckBoxCellRenderer());
	}
	
	/**
	 * This will add a file to the list. A new check box (instance of
	 * <code>FileCheckBox</code>) is created for the file. The checkbox is then
	 * displayed in the list.<br>
	 * 
	 * @param f
	 *           <code>File</code> to be added.
	 * @return A checbox created for the specified file.
	 */
	private FileCheckBoxModel addFile(File f){
		FileCheckBoxModel checkBox = new FileCheckBoxModel(f);
		model.addElement(checkBox);
		return checkBox;
	}
	
	/**
	 * This will populate the list with files (but not folders!) in the specified
	 * folder. The list is cleared first, then for each file in the specified
	 * folder the <code>addFile</code> method is called.
	 * 
	 * @param folder
	 *           A folder to be filled.
	 * @return Mapping of created checkboxes to each of the folder's files.
	 * @throws IllegalArgumentException
	 *            When the provided <code>File</code> is not a directory.
	 */
	public Collection<FileCheckBoxModel> fillFolder(File folder) 
		throws IllegalArgumentException
	{
		if(!folder.isDirectory()){
			throw new IllegalArgumentException("Specified File was not a folder!");
		}
		
		removeAllFiles();
		
		Collection<FileCheckBoxModel> checkboxes = 
			new ArrayList<FileCheckBoxModel>();
		File[] files = folder.listFiles();
		//can happen for link to folders --> they register as folders, but have 
		//no children
		if(files != null){
			for(int i = 0; i < files.length; i++){
				if(files[i].isFile()){
					checkboxes.add(addFile(files[i]));
				}
			}
		}
		return checkboxes;
	}

	/**
	 * This will fill the list with already prepared collection of
	 * <code>FileCheckBox</code>es. This is used when there is a need for
	 * displaying again folder that was displayed earlier before and we don't
	 * want to create new instances of <code>FileCheckBoxes</code>.
	 * 
	 * @param fileCheckboxes
	 *           Prepared collection of <code>FileCheckBoxes</code>
	 */
	public void fillPreparedFolder(Collection<FileCheckBoxModel> fileCheckboxes){
		removeAllFiles();
		for(FileCheckBoxModel cb : fileCheckboxes){
			model.addElement(cb);
		}
	}
	
	/**
	 * This removes the specified file from the list and from the underlying
	 * mapping. Reference to the corresponding checkbox is no longer held.
	 * 
	 * @param f
	 *           File to be removed.
	 */
	public void removeFile(File f){
		int size = model.getSize();
		for(int i = 0; i < size; i++){
			FileCheckBoxModel checkbox = (FileCheckBoxModel)model.getElementAt(i);
			if(checkbox.getFile().equals(f)){
				model.remove(i);
				return;
			}
		}
	}
	
	/**
	 * This will remove all files from the list and clear the underlying mapping.
	 * References to all checkboxes are lost.
	 */
	public void removeAllFiles(){
		model.removeAllElements();
	}
	
	/**
	 * This is an implementation of <code>ListCellRenderer</code> interface to
	 * support displaying checkboxes with file names and icons in a list.
	 * 
	 * @author Jakub Závěrka
	 */
	private class CheckBoxCellRenderer implements ListCellRenderer
	{
		/**
		 * Because we know that all items in the list are in fact checkboxes (
		 * <code>FileCheckBoxModel</code>, this will return the checkbox's
		 * grpahicalRepresentation, after retyping it from the <code>Object</code>
		 * . This ensures that every checkbox in the list will get painted
		 * correctly. Background will be set to that of the underlying list, or
		 * light blue, if the current component is the selected one.
		 */
		@Override public Component getListCellRendererComponent(JList list,
					Object value, int index, boolean isSelected, 
					boolean cellHasFocus)
		{
			Component val = ((FileCheckBoxModel)value).
				getGraphicalRepresentation();
			val.setBackground(isSelected ? new Color(127, 127, 255) : list
						.getBackground());
			return val;
		}
	}
}
